home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / accum.c < prev    next >
C/C++ Source or Header  |  1999-02-04  |  10KB  |  367 lines

  1. /* $Id: accum.c,v 3.2 1998/07/17 03:26:09 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: accum.c,v $
  26.  * Revision 3.2  1998/07/17 03:26:09  brianp
  27.  * include masking.h
  28.  *
  29.  * Revision 3.1  1998/06/30 04:08:47  brianp
  30.  * glAccum(GL_RETURN, s) didn't obey glColorMask() settings
  31.  *
  32.  * Revision 3.0  1998/01/31 20:46:29  brianp
  33.  * initial rev
  34.  *
  35.  */
  36.  
  37.  
  38. #ifdef PC_HEADER
  39. #include "all.h"
  40. #else
  41. #include <limits.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include "accum.h"
  45. #include "context.h"
  46. #include "macros.h"
  47. #include "masking.h"
  48. #include "span.h"
  49. #include "types.h"
  50. #endif
  51.  
  52.  
  53. void gl_alloc_accum_buffer( GLcontext *ctx )
  54. {
  55.    GLint n;
  56.  
  57.    if (ctx->Buffer->Accum) {
  58.       free( ctx->Buffer->Accum );
  59.       ctx->Buffer->Accum = NULL;
  60.    }
  61.  
  62.    /* allocate accumulation buffer if not already present */
  63.    n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
  64.    ctx->Buffer->Accum = (GLaccum *) malloc( n );
  65.    if (!ctx->Buffer->Accum) {
  66.       /* unable to setup accumulation buffer */
  67.       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
  68.    }
  69. }
  70.  
  71.  
  72.  
  73. void gl_ClearAccum( GLcontext *ctx,
  74.             GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
  75. {
  76.    if (INSIDE_BEGIN_END(ctx)) {
  77.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  78.       return;
  79.    }
  80.    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
  81.    ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
  82.    ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
  83.    ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
  84. }
  85.  
  86.  
  87.  
  88.  
  89. void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
  90. {
  91.    GLuint xpos, ypos, width, height;
  92.    GLfloat acc_scale;
  93.  
  94.    if (INSIDE_BEGIN_END(ctx)) {
  95.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  96.       return;
  97.    }
  98.  
  99.    if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
  100.       /* No accumulation buffer! */
  101.       gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
  102.       return;
  103.    }
  104.  
  105.    if (sizeof(GLaccum)==1) {
  106.       acc_scale = 127.0;
  107.    }
  108.    else if (sizeof(GLaccum)==2) {
  109.       acc_scale = 32767.0;
  110.    }
  111.    else {
  112.       /* sizeof(GLaccum) > 2 (Cray) */
  113.       acc_scale = (float) SHRT_MAX;
  114.    }
  115.  
  116.    if (ctx->NewState)
  117.       gl_update_state( ctx );
  118.  
  119.    /* Determine region to operate upon. */
  120.    if (ctx->Scissor.Enabled) {
  121.       xpos = ctx->Scissor.X;
  122.       ypos = ctx->Scissor.Y;
  123.       width = ctx->Scissor.Width;
  124.       height = ctx->Scissor.Height;
  125.    }
  126.    else {
  127.       /* whole window */
  128.       xpos = 0;
  129.       ypos = 0;
  130.       width = ctx->Buffer->Width;
  131.       height = ctx->Buffer->Height;
  132.    }
  133.  
  134.    switch (op) {
  135.       case GL_ADD:
  136.      {
  137.         GLaccum ival, *acc;
  138.         GLuint i, j;
  139.  
  140.         ival = (GLaccum) (value * acc_scale);
  141.         for (j=0;j<height;j++) {
  142.            acc = ctx->Buffer->Accum
  143.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  144.            for (i=0;i<width;i++) {
  145.           *acc += ival;   acc++;   /* red */
  146.           *acc += ival;   acc++;   /* green */
  147.           *acc += ival;   acc++;   /* blue */
  148.           *acc += ival;   acc++;   /* alpha */
  149.            }
  150.            ypos++;
  151.         }
  152.      }
  153.      break;
  154.       case GL_MULT:
  155.      {
  156.         GLaccum *acc;
  157.         GLuint i, j;
  158.  
  159.         for (j=0;j<height;j++) {
  160.            acc = ctx->Buffer->Accum
  161.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  162.            for (i=0;i<width;i++) {
  163.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*r*/
  164.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*g*/
  165.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*g*/
  166.           *acc = (GLaccum) ( (GLfloat) *acc * value );    acc++; /*a*/
  167.            }
  168.            ypos++;
  169.         }
  170.      }
  171.      break;
  172.       case GL_ACCUM:
  173.      {
  174.         GLaccum *acc;
  175.         GLubyte rgba[MAX_WIDTH][4];
  176.         GLfloat rscale, gscale, bscale, ascale;
  177.         GLuint i, j;
  178.  
  179.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  180.  
  181.         /* Accumulate */
  182.         rscale = value * acc_scale / 255.0;
  183.         gscale = value * acc_scale / 255.0;
  184.         bscale = value * acc_scale / 255.0;
  185.         ascale = value * acc_scale / 255.0;
  186.         for (j=0;j<height;j++) {
  187.            gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
  188.            acc = ctx->Buffer->Accum
  189.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  190.            for (i=0;i<width;i++) {
  191.           *acc += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );  acc++;
  192.           *acc += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );  acc++;
  193.           *acc += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );  acc++;
  194.           *acc += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );  acc++;
  195.            }
  196.            ypos++;
  197.         }
  198.  
  199.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  200.      }
  201.      break;
  202.       case GL_LOAD:
  203.      {
  204.         GLaccum *acc;
  205.         GLubyte rgba[MAX_WIDTH][4];
  206.         GLfloat rscale, gscale, bscale, ascale;
  207.         GLuint i, j;
  208.  
  209.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  210.  
  211.         /* Load accumulation buffer */
  212.         rscale = value * acc_scale / 255.0;
  213.         gscale = value * acc_scale / 255.0;
  214.         bscale = value * acc_scale / 255.0;
  215.         ascale = value * acc_scale / 255.0;
  216.         for (j=0;j<height;j++) {
  217.            gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
  218.            acc = ctx->Buffer->Accum
  219.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  220.            for (i=0;i<width;i++) {
  221.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );
  222.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );
  223.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );
  224.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );
  225.            }
  226.            ypos++;
  227.         }
  228.  
  229.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  230.      }
  231.      break;
  232.       case GL_RETURN:
  233.      {
  234.         GLubyte rgba[MAX_WIDTH][4];
  235.         GLaccum *acc;
  236.         GLfloat rscale, gscale, bscale, ascale;
  237.         GLuint i, j;
  238.  
  239.         rscale = value / acc_scale * 255.0F;
  240.         gscale = value / acc_scale * 255.0F;
  241.         bscale = value / acc_scale * 255.0F;
  242.         ascale = value / acc_scale * 255.0F;
  243.         for (j=0;j<height;j++) {
  244.            acc = ctx->Buffer->Accum
  245.              + (ypos * ctx->Buffer->Width + xpos) * 4;
  246.            for (i=0;i<width;i++) {
  247.           GLint r, g, b, a;
  248.           r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
  249.           g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
  250.           b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
  251.           a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
  252.           rgba[i][RCOMP] = CLAMP( r, 0, 255 );
  253.           rgba[i][GCOMP] = CLAMP( g, 0, 255 );
  254.           rgba[i][BCOMP] = CLAMP( b, 0, 255 );
  255.           rgba[i][ACOMP] = CLAMP( a, 0, 255 );
  256.            }
  257.            if (ctx->Color.SWmasking) {
  258.           gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
  259.            }
  260. #ifndef __STORM__
  261.            (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, rgba, NULL );
  262. #else
  263.            (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, (CONST GLubyte(*)[4])rgba, NULL );
  264. #endif
  265.            ypos++;
  266.         }
  267.      }
  268.      break;
  269.       default:
  270.      gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
  271.    }
  272. }
  273.  
  274.  
  275.  
  276.  
  277. /*
  278.  * Clear the accumulation Buffer->
  279.  */
  280. void gl_clear_accum_buffer( GLcontext *ctx )
  281. {
  282.    GLuint buffersize;
  283.    GLfloat acc_scale;
  284.  
  285.    if (ctx->Visual->AccumBits==0) {
  286.       /* No accumulation buffer! */
  287.       return;
  288.    }
  289.  
  290.    if (sizeof(GLaccum)==1) {
  291.       acc_scale = 127.0;
  292.    }
  293.    else if (sizeof(GLaccum)==2) {
  294.       acc_scale = 32767.0;
  295.    }
  296.    else {
  297.       /* sizeof(GLaccum) > 2 (Cray) */
  298.       acc_scale = (float) SHRT_MAX;
  299.    }
  300.  
  301.    /* number of pixels */
  302.    buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
  303.  
  304.    if (!ctx->Buffer->Accum) {
  305.       /* try to alloc accumulation buffer */
  306.       ctx->Buffer->Accum = (GLaccum *)
  307.                malloc( buffersize * 4 * sizeof(GLaccum) );
  308.    }
  309.  
  310.    if (ctx->Buffer->Accum) {
  311.       if (ctx->Scissor.Enabled) {
  312.      /* Limit clear to scissor box */
  313.      GLaccum r, g, b, a;
  314.      GLint i, j;
  315.      GLint width, height;
  316.      GLaccum *row;
  317.      r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  318.      g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  319.      b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  320.      a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  321.      /* size of region to clear */
  322.      width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
  323.      height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  324.      /* ptr to first element to clear */
  325.      row = ctx->Buffer->Accum
  326.            + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
  327.               + ctx->Buffer->Xmin);
  328.      for (j=0;j<height;j++) {
  329.         for (i=0;i<width;i+=4) {
  330.            row[i+0] = r;
  331.            row[i+1] = g;
  332.            row[i+2] = b;
  333.            row[i+3] = a;
  334.         }
  335.         row += 4 * ctx->Buffer->Width;
  336.      }
  337.       }
  338.       else {
  339.      /* clear whole buffer */
  340.      if (ctx->Accum.ClearColor[0]==0.0 &&
  341.          ctx->Accum.ClearColor[1]==0.0 &&
  342.          ctx->Accum.ClearColor[2]==0.0 &&
  343.          ctx->Accum.ClearColor[3]==0.0) {
  344.         /* Black */
  345.         MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
  346.      }
  347.      else {
  348.         /* Not black */
  349.         GLaccum *acc, r, g, b, a;
  350.         GLuint i;
  351.  
  352.         acc = ctx->Buffer->Accum;
  353.         r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  354.         g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  355.         b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  356.         a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  357.         for (i=0;i<buffersize;i++) {
  358.            *acc++ = r;
  359.            *acc++ = g;
  360.            *acc++ = b;
  361.            *acc++ = a;
  362.         }
  363.      }
  364.       }
  365.    }
  366. }
  367.